Skip to content

New architecture - WIP#9

Open
NellowTCS wants to merge 20 commits intov2.0.0from
new-architecture
Open

New architecture - WIP#9
NellowTCS wants to merge 20 commits intov2.0.0from
new-architecture

Conversation

@NellowTCS
Copy link
Copy Markdown
Member

No description provided.

@codesandbox
Copy link
Copy Markdown

codesandbox Bot commented Mar 16, 2026

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 16, 2026

Deploy Preview for htmlplayer-v2 ready!

Name Link
🔨 Latest commit 62e90ea
🔍 Latest deploy log https://app.netlify.com/projects/htmlplayer-v2/deploys/69d9b684be7f7500089d8e5c
😎 Deploy Preview https://deploy-preview-9--htmlplayer-v2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 16, 2026

Important

Review skipped

Too many files!

This PR contains 299 files, which is 149 over the limit of 150.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c4f800c4-5020-4ab5-b20b-6c3912eeaba7

📥 Commits

Reviewing files that changed from the base of the PR and between 4291f41 and 62e90ea.

⛔ Files ignored due to path filters (1)
  • Build/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (299)
  • Build/index.html
  • Build/jest.config.cjs
  • Build/package.json
  • Build/privacy.html
  • Build/public/privacy.html
  • Build/public/tos.html
  • Build/src/components/Miniplayer.tsx
  • Build/src/components/Player.tsx
  • Build/src/components/Playlist.tsx
  • Build/src/components/Settings.tsx
  • Build/src/components/Visualizer.tsx
  • Build/src/constants/pip.ts
  • Build/src/contexts/audioStore.ts
  • Build/src/core/engine/engine.ts
  • Build/src/core/engine/events.ts
  • Build/src/core/engine/index.ts
  • Build/src/core/engine/queue/index.ts
  • Build/src/core/engine/scheduler/index.ts
  • Build/src/core/engine/state/index.ts
  • Build/src/core/engine/types.ts
  • Build/src/data/legal.ts
  • Build/src/global.css
  • Build/src/helpers/audioProcessor.ts
  • Build/src/helpers/cacheManager.ts
  • Build/src/helpers/crossfadeHelper.ts
  • Build/src/helpers/crossfadeUtils.ts
  • Build/src/helpers/discordService_backup.ts
  • Build/src/helpers/filePickerHelper.tsx
  • Build/src/helpers/floProcessor.ts
  • Build/src/helpers/gaplessHelper.ts
  • Build/src/helpers/iconLoader.tsx
  • Build/src/helpers/importAudioFiles.tsx
  • Build/src/helpers/logger.ts
  • Build/src/helpers/musicIndexedDbHelper.ts
  • Build/src/helpers/musicPlayerUtils.ts
  • Build/src/helpers/pitchShiftHelper.ts
  • Build/src/helpers/platform.ts
  • Build/src/helpers/playlistImageHelper.ts
  • Build/src/helpers/playlistManager.ts
  • Build/src/helpers/refloWavHelper.ts
  • Build/src/helpers/safariHelper.ts
  • Build/src/helpers/shuffleManager.ts
  • Build/src/helpers/themeLoader.tsx
  • Build/src/helpers/themeMetadata.ts
  • Build/src/helpers/themeMode.ts
  • Build/src/helpers/wallpaperLoader.tsx
  • Build/src/hooks/musicPlayerHook.tsx
  • Build/src/hooks/useAlbumArt.tsx
  • Build/src/hooks/useAudioSync.ts
  • Build/src/hooks/useDialogVisibility.ts
  • Build/src/hooks/useFileHandler.ts
  • Build/src/hooks/useFilePicker.tsx
  • Build/src/hooks/useKeyboardShortcuts.ts
  • Build/src/hooks/useKomorebi.ts
  • Build/src/hooks/useShareTarget.ts
  • Build/src/hooks/useVisualizerCanvas.ts
  • Build/src/locales/en/loading-messages-en.json
  • Build/src/locales/en/tour.json
  • Build/src/locales/en/translation.json
  • Build/src/locales/fr/translation.json
  • Build/src/pages/_index.tsx
  • Build/src/pages/main.tsx
  • Build/src/pages/privacy.tsx
  • Build/src/pages/privacyEntry.tsx
  • Build/src/pages/terms.tsx
  • Build/src/pages/termsEntry.tsx
  • Build/src/platform/audio/backends/BaseBackend.ts
  • Build/src/platform/audio/backends/FloBackend.ts
  • Build/src/platform/audio/backends/HTMLBackend.ts
  • Build/src/platform/audio/backends/HybridBackend.ts
  • Build/src/platform/audio/backends/PitchBackend.ts
  • Build/src/platform/audio/backends/WebAudioBackend.ts
  • Build/src/platform/audio/backends/index.ts
  • Build/src/platform/audio/equalizer.ts
  • Build/src/platform/audio/floDecoder.ts
  • Build/src/platform/audio/floWavDecoder.ts
  • Build/src/platform/audio/index.ts
  • Build/src/platform/audio/preloader.ts
  • Build/src/platform/audio/replayGain.ts
  • Build/src/platform/integrations/base.ts
  • Build/src/platform/integrations/discord.ts
  • Build/src/platform/integrations/discordService.ts
  • Build/src/platform/integrations/index.ts
  • Build/src/platform/integrations/mediaSession.ts
  • Build/src/platform/integrations/shareTarget.ts
  • Build/src/platform/library/duplicateDetector.ts
  • Build/src/platform/library/index.ts
  • Build/src/platform/library/library.ts
  • Build/src/platform/library/persistence.ts
  • Build/src/platform/library/scoring.ts
  • Build/src/platform/library/smartPlaylist.ts
  • Build/src/platform/library/types.ts
  • Build/src/platform/lyrics/index.ts
  • Build/src/platform/lyrics/metadataFilter.ts
  • Build/src/platform/metadata/base.ts
  • Build/src/platform/metadata/floMetadata.ts
  • Build/src/platform/metadata/index.ts
  • Build/src/platform/metadata/musicMetadata.ts
  • Build/src/platform/pip/broadcastTheme.ts
  • Build/src/platform/pip/index.tsx
  • Build/src/platform/providers/albumArtManager.ts
  • Build/src/platform/providers/albumArtTypes.ts
  • Build/src/platform/providers/base.ts
  • Build/src/platform/providers/discogs.ts
  • Build/src/platform/providers/index.ts
  • Build/src/platform/providers/lrcParser.ts
  • Build/src/platform/providers/lyricsManager.ts
  • Build/src/platform/providers/lyricsOvh.ts
  • Build/src/platform/providers/lyricsTypes.ts
  • Build/src/platform/providers/musicBrainz.ts
  • Build/src/platform/settings/index.ts
  • Build/src/platform/settings/persistence.ts
  • Build/src/platform/settings/settings.ts
  • Build/src/platform/settings/types.ts
  • Build/src/platform/storage/albumArt.ts
  • Build/src/platform/storage/audio.ts
  • Build/src/platform/storage/base.ts
  • Build/src/platform/storage/db.ts
  • Build/src/platform/storage/desktopStorage.ts
  • Build/src/platform/storage/dialogs.ts
  • Build/src/platform/storage/fileHandler.ts
  • Build/src/platform/storage/index.ts
  • Build/src/platform/storage/playlistStorage.ts
  • Build/src/platform/storage/settingsStorage.ts
  • Build/src/platform/storage/shortcuts.ts
  • Build/src/platform/storage/trackStorage.ts
  • Build/src/platform/storage/unifiedDB.ts
  • Build/src/platform/storage/webStorage.ts
  • Build/src/platform/utils/fileValidation.ts
  • Build/src/platform/utils/id.ts
  • Build/src/platform/utils/playlistImage.ts
  • Build/src/platform/utils/safari.ts
  • Build/src/platform/utils/session.ts
  • Build/src/platform/visualizers/index.ts
  • Build/src/platform/visualizers/visualizerLoader.ts
  • Build/src/themes/Icons/Bootstrap/Bootstrap.theme.json
  • Build/src/themes/Icons/Css.gg/css-gg.theme.json
  • Build/src/themes/Icons/Lucide/Lucide.theme.json
  • Build/src/themes/Icons/Material Design/MaterialDesign.theme.json
  • Build/src/themes/Icons/Phosphor/Phosphor.theme.json
  • Build/src/themes/Icons/Remix Icon/RemixIcon.theme.json
  • Build/src/themes/Icons/Simple Line Icons/SimpleLineIcons.theme.json
  • Build/src/themes/Icons/Tabler Icons/TablerIcons.theme.json
  • Build/src/themes/Themes/Aurora/Aurora.theme.css
  • Build/src/themes/Themes/BlackHole/BlackHole.theme.css
  • Build/src/themes/Themes/Blue/Blue.theme.css
  • Build/src/themes/Themes/CottonCandy/CottonCandy.theme.css
  • Build/src/themes/Themes/Cyberpunk/Cyberpunk.theme.css
  • Build/src/themes/Themes/Forest/Forest.theme.css
  • Build/src/themes/Themes/Frosty/Frosty.theme.css
  • Build/src/themes/Themes/Lumenis/Lumenis.theme.css
  • Build/src/themes/Themes/LunarEclipse/LunarEclipse.theme.css
  • Build/src/themes/Themes/Mirage/Mirage.theme.css
  • Build/src/themes/Themes/Monochrome/Monochrome.theme.css
  • Build/src/themes/Themes/MurderDrones/Drones.theme.css
  • Build/src/themes/Themes/Nebula/Nebula.theme.css
  • Build/src/themes/Themes/NorthernLights/NorthernLights.theme.css
  • Build/src/themes/Themes/Obsidian/Obsidian.theme.css
  • Build/src/themes/Themes/Ocean/Ocean.theme.css
  • Build/src/themes/Themes/Orange/Orange.theme.css
  • Build/src/themes/Themes/Rainbow/Rainbow.theme.css
  • Build/src/themes/Themes/Red/Red.theme.css
  • Build/src/themes/Themes/Sakura/Sakura.theme.css
  • Build/src/themes/Themes/SolarEclipse/SolarEclipse.theme.css
  • Build/src/themes/Themes/StellarGlow/StellarGlow.theme.css
  • Build/src/themes/Themes/Sun/Sun.theme.css
  • Build/src/themes/Themes/Terracotta/Terracotta.theme.css
  • Build/src/themes/Themes/Twilight/Twilight.theme.css
  • Build/src/themes/Themes/Verdant/Verdant.theme.css
  • Build/src/themes/Themes/Win95/Win95.theme.css
  • Build/src/themes/Themes/Yellow/Yellow.theme.css
  • Build/src/types/MusicLibrary.d.ts
  • Build/src/types/MusicPlayerTypes.d.ts
  • Build/src/types/PlayerSettings.d.ts
  • Build/src/types/PlayerState.d.ts
  • Build/src/types/Playlist.d.ts
  • Build/src/types/Song.d.ts
  • Build/src/types/Wallpaper.d.ts
  • Build/src/types/custom-events.d.ts
  • Build/src/types/vite-env.d.ts
  • Build/src/ui/AppShell.tsx
  • Build/src/ui/components/features/Home.module.css
  • Build/src/ui/components/features/Home.tsx
  • Build/src/ui/components/features/Playlist.module.css
  • Build/src/ui/components/features/Playlist.tsx
  • Build/src/ui/components/features/PlaylistToolbar.tsx
  • Build/src/ui/components/features/Settings.module.css
  • Build/src/ui/components/features/Settings.tsx
  • Build/src/ui/components/features/SettingsAudio.tsx
  • Build/src/ui/components/features/SettingsExperimental.tsx
  • Build/src/ui/components/features/SettingsInterface.tsx
  • Build/src/ui/components/features/SettingsPlayback.tsx
  • Build/src/ui/components/features/SettingsShortcuts.tsx
  • Build/src/ui/components/features/Wallpaper.tsx
  • Build/src/ui/components/features/index.ts
  • Build/src/ui/components/index.ts
  • Build/src/ui/components/layout/MainContent.module.css
  • Build/src/ui/components/layout/MainContent.tsx
  • Build/src/ui/components/layout/MainContentHeader.tsx
  • Build/src/ui/components/layout/SelectSongsMenu.tsx
  • Build/src/ui/components/layout/Sidebar.module.css
  • Build/src/ui/components/layout/Sidebar.tsx
  • Build/src/ui/components/layout/SortDropdown.tsx
  • Build/src/ui/components/layout/index.ts
  • Build/src/ui/components/player/Lyrics.module.css
  • Build/src/ui/components/player/Lyrics.tsx
  • Build/src/ui/components/player/Miniplayer.module.css
  • Build/src/ui/components/player/Miniplayer.tsx
  • Build/src/ui/components/player/Player.module.css
  • Build/src/ui/components/player/Player.tsx
  • Build/src/ui/components/player/PlayerAlbumArt.tsx
  • Build/src/ui/components/player/PlayerControls.tsx
  • Build/src/ui/components/player/PlayerSecondaryControls.tsx
  • Build/src/ui/components/player/PlayerTrackInfo.tsx
  • Build/src/ui/components/player/ProgressBar.tsx
  • Build/src/ui/components/player/Visualizer.module.css
  • Build/src/ui/components/player/Visualizer.tsx
  • Build/src/ui/components/player/VolumeControl.tsx
  • Build/src/ui/components/player/index.ts
  • Build/src/ui/components/primitives/Button.module.css
  • Build/src/ui/components/primitives/Button.tsx
  • Build/src/ui/components/primitives/Checkbox.module.css
  • Build/src/ui/components/primitives/Checkbox.tsx
  • Build/src/ui/components/primitives/Collapsible.tsx
  • Build/src/ui/components/primitives/ConfirmDialog.tsx
  • Build/src/ui/components/primitives/DeleteDialog.tsx
  • Build/src/ui/components/primitives/Dialog.module.css
  • Build/src/ui/components/primitives/Dialog.tsx
  • Build/src/ui/components/primitives/Draggable.module.css
  • Build/src/ui/components/primitives/Draggable.tsx
  • Build/src/ui/components/primitives/DropdownMenu.module.css
  • Build/src/ui/components/primitives/DropdownMenu.tsx
  • Build/src/ui/components/primitives/FolderItem.tsx
  • Build/src/ui/components/primitives/Input.module.css
  • Build/src/ui/components/primitives/Input.tsx
  • Build/src/ui/components/primitives/PersistentDropdownMenu.module.css
  • Build/src/ui/components/primitives/PersistentDropdownMenu.tsx
  • Build/src/ui/components/primitives/PlaylistItem.tsx
  • Build/src/ui/components/primitives/ResetDialogsDialog.tsx
  • Build/src/ui/components/primitives/SearchInput.module.css
  • Build/src/ui/components/primitives/SearchInput.tsx
  • Build/src/ui/components/primitives/Select.module.css
  • Build/src/ui/components/primitives/Select.tsx
  • Build/src/ui/components/primitives/Separator.module.css
  • Build/src/ui/components/primitives/Separator.tsx
  • Build/src/ui/components/primitives/Sheet.module.css
  • Build/src/ui/components/primitives/Sheet.tsx
  • Build/src/ui/components/primitives/Slider.module.css
  • Build/src/ui/components/primitives/Slider.tsx
  • Build/src/ui/components/primitives/Switch.module.css
  • Build/src/ui/components/primitives/Switch.tsx
  • Build/src/ui/components/primitives/Tooltip.module.css
  • Build/src/ui/components/primitives/Tooltip.tsx
  • Build/src/ui/components/primitives/index.ts
  • Build/src/ui/components/shared/AddToPopover.tsx
  • Build/src/ui/components/shared/HelpGuide.module.css
  • Build/src/ui/components/shared/HelpGuide.tsx
  • Build/src/ui/components/shared/Icon.tsx
  • Build/src/ui/components/shared/ScrollText.module.css
  • Build/src/ui/components/shared/ScrollText.tsx
  • Build/src/ui/components/shared/ShortcutConfig.tsx
  • Build/src/ui/components/shared/SongActionsDropdown.tsx
  • Build/src/ui/components/shared/ThemeModeSwitch.module.css
  • Build/src/ui/components/shared/ThemeModeSwitch.tsx
  • Build/src/ui/components/shared/UpdatePrompt.module.css
  • Build/src/ui/components/shared/UpdatePrompt.tsx
  • Build/src/ui/components/shared/index.ts
  • Build/src/ui/hooks/index.ts
  • Build/src/ui/hooks/useDragHandler.ts
  • Build/src/ui/miniplayer/MiniplayerEngine.ts
  • Build/src/ui/miniplayer/events.ts
  • Build/src/ui/miniplayer/index.ts
  • Build/src/ui/navigation/NavigationProvider.tsx
  • Build/src/ui/navigation/index.ts
  • Build/src/ui/pages/LegalPage.module.css
  • Build/src/ui/pages/LegalPage.tsx
  • Build/src/ui/resources/themes/Icons/Bootstrap/Bootstrap.icons.ts
  • Build/src/ui/resources/themes/Icons/Bootstrap/Bootstrap.theme.json
  • Build/src/ui/resources/themes/Icons/Css.gg/css-gg.icons.ts
  • Build/src/ui/resources/themes/Icons/Css.gg/css-gg.theme.json
  • Build/src/ui/resources/themes/Icons/Lucide/Lucide.icons.ts
  • Build/src/ui/resources/themes/Icons/Lucide/Lucide.theme.json
  • Build/src/ui/resources/themes/Icons/Material Design/MaterialDesign.icons.ts
  • Build/src/ui/resources/themes/Icons/Material Design/MaterialDesign.theme.json
  • Build/src/ui/resources/themes/Icons/Phosphor/Phosphor.icons.ts
  • Build/src/ui/resources/themes/Icons/Phosphor/Phosphor.theme.json
  • Build/src/ui/resources/themes/Icons/Remix Icon/RemixIcon.icons.ts
  • Build/src/ui/resources/themes/Icons/Remix Icon/RemixIcon.theme.json
  • Build/src/ui/resources/themes/Icons/Simple Line Icons/SimpleLineIcons.icons.ts
  • Build/src/ui/resources/themes/Icons/Simple Line Icons/SimpleLineIcons.theme.json
  • Build/src/ui/resources/themes/Icons/Tabler Icons/TablerIcons.icons.ts
  • Build/src/ui/resources/themes/Icons/Tabler Icons/TablerIcons.theme.json
  • Build/src/ui/resources/themes/Palettes/50Shades/50Shades.theme.css
  • Build/src/ui/resources/themes/Palettes/50Shades/50Shades.theme.json
  • Build/src/ui/resources/themes/Palettes/Aurora/Aurora.theme.css
  • Build/src/ui/resources/themes/Palettes/Aurora/Aurora.theme.json
  • Build/src/ui/resources/themes/Palettes/BlackHole/BlackHole.theme.css
  • Build/src/ui/resources/themes/Palettes/BlackHole/BlackHole.theme.json
  • Build/src/ui/resources/themes/Palettes/Blue/Blue.theme.css

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch new-architecture

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@NellowTCS NellowTCS force-pushed the new-architecture branch 2 times, most recently from 8bddc8b to 6c8e629 Compare March 17, 2026 05:28
@NellowTCS
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 1, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@NellowTCS
Copy link
Copy Markdown
Member Author

@coderabbitai review src/engine src/core src/hooks

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 1, 2026

@NellowTCS Sure! I'll review the changes in src/engine, src/core, and src/hooks for you.

Please focus the review on the following paths: src/engine, src/core, and src/hooks.

✅ Actions performed

Full review triggered.

@NellowTCS NellowTCS self-assigned this Apr 1, 2026
@NellowTCS NellowTCS requested a review from Copilot April 1, 2026 21:56
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces a new WIP architecture by adding a modular core engine + platform layer (audio backends, library management, integrations) and refactoring the app entry/UI to consume the new abstractions (including new privacy/terms pages and updated theming setup).

Changes:

  • Added a new core/engine foundation (types, events, state machine, queue, scheduler).
  • Added platform/* modules for library, audio (backends/decoders/effects), and integrations (MediaSession/Discord/share target).
  • Refactored the main page entry to use the new useKomorebi + AppShell composition and moved legal pages into React routes/entries.

Reviewed changes

Copilot reviewed 91 out of 464 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
Build/src/platform/lyrics/index.ts Re-exports lyrics metadata filter utilities.
Build/src/platform/library/types.ts Defines library state/actions/events types for new library layer.
Build/src/platform/library/smartPlaylist.ts Adds a rule-based smart playlist generator built on scoring state.
Build/src/platform/library/scoring.ts Introduces per-track scoring engine used for shuffle/playlists.
Build/src/platform/library/persistence.ts Adds persistence wrapper around storage modules for library data.
Build/src/platform/library/library.ts Implements LibraryManager and playlist/folder helpers.
Build/src/platform/library/index.ts Barrels exports for the new library module.
Build/src/platform/library/duplicateDetector.ts Adds duplicate detection via hashing and metadata signatures.
Build/src/platform/integrations/shareTarget.ts Implements share-target parsing and cache retrieval for shared files/text.
Build/src/platform/integrations/mediaSession.ts Adds Media Session integration with action handlers + metadata updates.
Build/src/platform/integrations/index.ts Barrels exports for integrations.
Build/src/platform/integrations/discordService.ts Reworks Discord service logging to use the new logger.
Build/src/platform/integrations/discord.ts Adds Discord integration wrapper around DiscordService.
Build/src/platform/integrations/base.ts Adds common integration base class + interface.
Build/src/platform/audio/replayGain.ts Adds ReplayGain analyzer + tag parsing helpers.
Build/src/platform/audio/preloader.ts Adds a track preloader with cache/TTL/eviction.
Build/src/platform/audio/index.ts Defines audio backend interfaces and factory types.
Build/src/platform/audio/floWavDecoder.ts Adds flo→wav decoder wrapper (reflo) with init guard.
Build/src/platform/audio/floDecoder.ts Adds flo decoder wrapper (libflo) to AudioBuffer + helpers.
Build/src/platform/audio/equalizer.ts Adds an equalizer implementation with presets and filter chain.
Build/src/platform/audio/backends/index.ts Adds backend manager selection and exports for audio backends.
Build/src/platform/audio/backends/WebAudioBackend.ts Adds WebAudio backend implementation with time updates + analyser.
Build/src/platform/audio/backends/PitchBackend.ts Adds pitch shifting backend wrapper using Tone.js PitchShift.
Build/src/platform/audio/backends/HybridBackend.ts Adds hybrid backend delegating to HTML/WebAudio backends.
Build/src/platform/audio/backends/HTMLBackend.ts Adds HTMLAudioElement backend implementation.
Build/src/platform/audio/backends/FloBackend.ts Adds flo-specific backend using libflo decoding + WebAudio playback.
Build/src/platform/audio/backends/BaseBackend.ts Adds shared callback management for backends (time/ended/error).
Build/src/pages/termsEntry.tsx Adds React entrypoint for Terms page with i18n/theme providers.
Build/src/pages/terms.tsx Adds Terms page wrapper around LegalPage.
Build/src/pages/privacyEntry.tsx Adds React entrypoint for Privacy page with i18n/theme providers.
Build/src/pages/privacy.tsx Adds Privacy page wrapper around LegalPage.
Build/src/pages/main.tsx Refactors app root render to new ThemeProvider + App component composition.
Build/src/pages/_index.tsx Replaces legacy page implementation with useKomorebi + AppShell.
Build/src/locales/fr/translation.json Adds common.confirm i18n string (FR).
Build/src/locales/en/translation.json Adds common.confirm i18n string (EN).
Build/src/hooks/useVisualizerCanvas.ts Extracts visualizer rendering into a dedicated hook.
Build/src/hooks/useShareTarget.ts Adds hook wrapper around share target handlers.
Build/src/hooks/useKeyboardShortcuts.ts Refactors keyboard shortcut hook to use new storage + Komorebi API.
Build/src/hooks/useFilePicker.tsx Adds Uppy-based audio file picker dialog.
Build/src/hooks/useFileHandler.ts Adds launchQueue-based file handler hook (PWA file opening).
Build/src/hooks/useDialogVisibility.ts Removes legacy dialog visibility hook (IndexedDB-based).
Build/src/hooks/useAudioSync.ts Removes legacy cross-window audio sync hook.
Build/src/hooks/useAlbumArt.tsx Switches album art caching/loading to new albumArtStorage.
Build/src/helpers/wallpaperLoader.tsx Removes legacy wallpaper loader/provider.
Build/src/helpers/themeMode.ts Removes legacy theme mode utilities + PiP theme broadcasting.
Build/src/helpers/themeMetadata.ts Removes legacy theme metadata loader.
Build/src/helpers/themeLoader.tsx Removes legacy theme loader/provider.
Build/src/helpers/shuffleManager.ts Removes legacy shuffle manager and next-song caching utilities.
Build/src/helpers/safariHelper.ts Removes legacy Safari background audio manager.
Build/src/helpers/refloWavHelper.ts Removes legacy flo→wav helper (moved to platform/audio).
Build/src/helpers/playlistImageHelper.ts Removes legacy playlist image generator helper.
Build/src/helpers/platform.ts Removes legacy platform abstraction helpers.
Build/src/helpers/pitchShiftHelper.ts Removes legacy pitch helpers.
Build/src/helpers/musicPlayerUtils.ts Removes legacy tempo/pitch playback rate helpers.
Build/src/helpers/logger.ts Introduces new Satori-based logging wrapper and throwError.
Build/src/helpers/importAudioFiles.tsx Refactors import pipeline to new metadata/audio/storage modules.
Build/src/helpers/gaplessHelper.ts Removes legacy gapless offset calculator.
Build/src/helpers/floProcessor.ts Removes legacy flo processing helpers (moved to platform/audio).
Build/src/helpers/discordService_backup.ts Removes backup Discord service implementation.
Build/src/helpers/audioProcessor.ts Removes legacy audio processor (IndexedDB + flo init).
Build/src/global.css Adds base theme import + new layout/util CSS patterns.
Build/src/data/legal.ts Adds legal document data as typed TS objects.
Build/src/core/engine/types.ts Adds engine domain types (track/playlist/state/events/config).
Build/src/core/engine/state/index.ts Adds a state machine with validated transitions + history.
Build/src/core/engine/scheduler/index.ts Adds crossfade/gapless schedulers + scheduler facade.
Build/src/core/engine/queue/index.ts Adds queue manager with shuffle and smart shuffle support.
Build/src/core/engine/index.ts Barrels exports for engine module.
Build/src/core/engine/events.ts Adds typed event emitter for engine events.
Build/src/contexts/audioStore.ts Removes legacy zustand audio store + BroadcastChannel syncing.
Build/src/constants/pip.ts Adds constants for PiP window sizing and theme variable list.
Build/src/components/Visualizer.tsx Removes legacy Visualizer component (replaced by hook/UI).
Build/src/components/Miniplayer.tsx Removes legacy PiP/Miniplayer implementation.
Build/public/tos.html Removes static public TOS page (moved into React legal pages).
Build/public/privacy.html Removes static public privacy page (moved into React legal pages).
Build/privacy.html Adds standalone privacy HTML entry wiring to React privacy entry.
Build/package.json Switches testing to Jest + adds Tone.js and Satori dependency changes.
Build/jest.config.cjs Adds Jest configuration (ts-jest, coverage, jsdom).
Build/index.html Updates default theme link path to new theme resource location.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +313 to +325
for (const item of items) {
if (item.id === id) return null;
if ("children" in item) {
for (const child of item.children) {
if (child.id === id) return item.id;
if ("children" in child) {
const found = findParentFolderId(item.children, id);
if (found) return found;
}
}
}
}
return null;
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recursive call uses findParentFolderId(item.children, id) instead of recursing into the child subtree. This re-traverses the same item.children array and can lead to incorrect results or runaway recursion when nested folders exist. Fix by recursing into the child's children (or restructure the traversal to recurse once per node).

Suggested change
for (const item of items) {
if (item.id === id) return null;
if ("children" in item) {
for (const child of item.children) {
if (child.id === id) return item.id;
if ("children" in child) {
const found = findParentFolderId(item.children, id);
if (found) return found;
}
}
}
}
return null;
function search(
nodes: (Playlist | PlaylistFolder)[],
parentId: string | null,
): string | null {
for (const item of nodes) {
if (item.id === id) {
return parentId;
}
if ("children" in item && item.children?.length) {
const found = search(item.children, item.id);
if (found) {
return found;
}
}
}
return null;
}
return search(items, null);

Copilot uses AI. Check for mistakes.
Comment on lines +65 to +69
if (this.loading.has(track.id)) {
return new Promise((resolve) => {
this.preloadCallbacks.set(track.id, resolve);
});
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concurrent callers to preload(track) while a load is in-flight will overwrite the previous resolver in preloadCallbacks, causing earlier Promises to never resolve. Store an array/set of resolvers per track ID, or replace the callback map with an inflight: Map<string, Promise<string>> and return the same Promise to all callers.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +26
export function setProcessingState(processing: boolean) {
if (processing) {
window.addEventListener("beforeunload", (e) => {
e.preventDefault();
e.returnValue = "";
});
} else {
window.removeEventListener("beforeunload", () => {});
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The beforeunload listener added is an anonymous function, but the removal uses a different anonymous function, so the listener is never removed (leaks and can wrongly block navigation later). Use a stable handler reference (module-level function, ref, or closure variable) for both add/remove.

Suggested change
export function setProcessingState(processing: boolean) {
if (processing) {
window.addEventListener("beforeunload", (e) => {
e.preventDefault();
e.returnValue = "";
});
} else {
window.removeEventListener("beforeunload", () => {});
const beforeUnloadHandler = (e: BeforeUnloadEvent) => {
e.preventDefault();
e.returnValue = "";
};
export function setProcessingState(processing: boolean) {
if (processing) {
window.addEventListener("beforeunload", beforeUnloadHandler);
} else {
window.removeEventListener("beforeunload", beforeUnloadHandler);

Copilot uses AI. Check for mistakes.
Comment on lines +86 to +91
setEnabled(enabled: boolean): void {
this.enabled = enabled;
if (this.gainNode) {
this.gainNode.gain.value = enabled ? 1 : 1;
}
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setEnabled(false) has no effect because it sets the gain to 1 in both branches. If the intent is to bypass the EQ, either (a) disconnect/reconnect the processing chain to bypass filters, or (b) set all filter gains to 0 when disabled and restore when enabled.

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +89
const source = ctx.createBufferSource();
source.buffer = this.chain.audioBuffer;
source.connect(this.chain.gainNode);

const analyser = this.ensureAnalyser();
this.chain.gainNode.connect(analyser);
analyser.connect(ctx.destination);
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each play() call reconnects gainNode -> analyser -> destination without disconnecting them, which can create multiple parallel connections that sum audio (volume increases) and leak nodes over time. Ensure the graph is connected exactly once (e.g., connect in ensureContext() and only reconnect the source, or disconnect/rebuild the chain on stop).

Copilot uses AI. Check for mistakes.
Comment thread Build/package.json
"start": "cd dist && python3 -m http.server 8000",
"preview": "vite preview",
"test": "react-scripts test",
"test": "jest",
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With test now mapped to plain jest, CI will fail if there are currently no tests. If the repo is mid-migration, consider aligning test to jest --passWithNoTests (and keep a stricter target for CI later), or add at least a minimal smoke test to keep the default test script meaningful.

Suggested change
"test": "jest",
"test": "jest --passWithNoTests",

Copilot uses AI. Check for mistakes.
Comment thread Build/package.json
"eslint": "^9.39.4",
"eslint-plugin-react": "^7.37.5",
"jest": "^29.7.0",
"jest-environment-jsdom": "^30.3.0",
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jest-environment-jsdom@^30.x targets Jest 30, but jest is pinned to ^29.7.0. This version mismatch commonly breaks Jest runtime resolution. Either bump Jest to 30.x (and ensure ts-jest compatibility) or downgrade jest-environment-jsdom to a 29.x version.

Suggested change
"jest-environment-jsdom": "^30.3.0",
"jest-environment-jsdom": "^29.7.0",

Copilot uses AI. Check for mistakes.
Comment on lines +132 to +136
return track.gapless?.encoderDelay ?? this.config.startOffset;
}

getEndOffset(track: Track): number {
return track.gapless?.encoderPadding ?? this.config.endOffset;
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gapless encoder delay/padding values are typically expressed in samples, not seconds. Subtracting raw encoderPadding from track.duration (seconds) can cause incorrect transition timing (potentially huge negative/positive offsets). Convert samples to seconds using track.encoding.sampleRate (or clarify/rename the units in GaplessInfo and ensure producers store seconds).

Suggested change
return track.gapless?.encoderDelay ?? this.config.startOffset;
}
getEndOffset(track: Track): number {
return track.gapless?.encoderPadding ?? this.config.endOffset;
const encoderDelay = track.gapless?.encoderDelay;
const sampleRate = (track as any).encoding?.sampleRate as number | undefined;
if (
typeof encoderDelay === "number" &&
typeof sampleRate === "number" &&
sampleRate > 0
) {
// encoderDelay is typically expressed in samples; convert to seconds
return encoderDelay / sampleRate;
}
return this.config.startOffset;
}
getEndOffset(track: Track): number {
const encoderPadding = track.gapless?.encoderPadding;
const sampleRate = (track as any).encoding?.sampleRate as number | undefined;
if (
typeof encoderPadding === "number" &&
typeof sampleRate === "number" &&
sampleRate > 0
) {
// encoderPadding is typically expressed in samples; convert to seconds
return encoderPadding / sampleRate;
}
return this.config.endOffset;

Copilot uses AI. Check for mistakes.
Comment on lines +144 to +147
calculatePlayEnd(track: Track): number {
const offset = this.getEndOffset(track);
return track.duration - offset;
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gapless encoder delay/padding values are typically expressed in samples, not seconds. Subtracting raw encoderPadding from track.duration (seconds) can cause incorrect transition timing (potentially huge negative/positive offsets). Convert samples to seconds using track.encoding.sampleRate (or clarify/rename the units in GaplessInfo and ensure producers store seconds).

Copilot uses AI. Check for mistakes.
Comment on lines +176 to +184
private updateMode(): void {
if (this.gapless.isEnabled() && this.gapless.getConfig().enabled) {
this.currentMode = "gapless";
} else if (this.crossfade.isEnabled()) {
this.currentMode = "crossfade";
} else {
this.currentMode = "none";
}
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this precedence, if gapless is enabled, crossfade mode is never selected even when crossfade is enabled. If crossfade is intended to override gapless when enabled (common behavior), swap the precedence or make the choice explicit via a single 'transition mode' setting.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants